/**
 * @file epd_hal.c
 * @brief HAL implementation for ESP32 + EPD.
 */
#include "epd_hal.h"
#include <string.h>

/* Underlying board support (Waveshare-style) */
/* These headers/functions are expected to exist in the current project. */
#if EPD_ENABLE
#include "DEV_Config.h"
#include "EPD_7in5bc.h"
#else
/* Stub when EPD_ENABLE is off */
#endif

static epd_hal_ctx_t s_hal;

static bool spi_apply_config(const epd_spi_config_t *cfg)
{
    /* Store CPOL/CPHA for documentation and debugging purposes. */
    /* Some DEV_Config implementations use fixed SPI mode 0. We do a best-effort. */
    (void)cfg; /* avoid unused warning if platform lacks runtime config */
#if EPD_ENABLE
    return true;
#else
    (void)cfg; return true;
#endif
}

epd_err_t epd_hal_init_spi(epd_hal_ctx_t *ctx, const epd_spi_config_t *cfg)
{
    if ((ctx == NULL) || (cfg == NULL)) {
        return EPD_ERR_PARAM;
    }
    if ((cfg->freq_hz < 1000000UL) || (cfg->freq_hz > 20000000UL)) {
        /* sanity: 1MHz..20MHz */
        return EPD_ERR_PARAM;
    }
    if ((cfg->mode > 3U) || ((cfg->cpol > 1U) || (cfg->cpha > 1U))) {
        return EPD_ERR_PARAM;
    }

    /* Apply config */
    (void)memcpy(&s_hal.spi_cfg, cfg, sizeof(epd_spi_config_t));
    (void)memcpy(&ctx->spi_cfg, cfg, sizeof(epd_spi_config_t));

    if (!spi_apply_config(cfg)) {
        return EPD_ERR_UNSUPPORTED;
    }

    /* DEV_Config is assumed to be pre-initialized elsewhere in the project.
       If needed, we could call DEV_Module_Init() here. */
    return EPD_OK;
}

/* SPI write helpers: when使用厂商驱动时，我们不直接下发命令数据，交由EPD_7IN5BC_*内部完成 */
epd_err_t epd_hal_spi_write_command(uint8_t cmd)
{
#if EPD_ENABLE
    (void)cmd; return EPD_ERR_UNSUPPORTED;
#else
    (void)cmd; return EPD_ERR_UNSUPPORTED;
#endif
}

epd_err_t epd_hal_spi_write_data(uint8_t data)
{
#if EPD_ENABLE
    (void)data; return EPD_ERR_UNSUPPORTED;
#else
    (void)data; return EPD_ERR_UNSUPPORTED;
#endif
}

void epd_hal_delay_ms(uint32_t ms)
{
#if EPD_ENABLE
    DEV_Delay_ms(ms);
#else
    (void)ms;
#endif
}

bool epd_hal_read_busy(void)
{
    /* Waveshare drivers use EPD_7IN5BC_ReadBusy() that blocks until idle.
       Here we provide a quick check by reading the BUSY pin if available. */
#ifdef GET_EPD_BUSY
#if EPD_ENABLE
    return (GET_EPD_BUSY() == 1);
#else
    return false;
#endif
#endif
    return false;
}

epd_err_t epd_hal_reset_sequence(void)
{
    /* Use the driver-provided reset. */
#if EPD_ENABLE
    return EPD_ERR_UNSUPPORTED;
#else
    return EPD_ERR_UNSUPPORTED;
#endif
}